import { Injectable } from '@nestjs/common';
import { CreateMenuDto } from './dto/create-menu.dto';
import { UpdateMenuDto } from './dto/update-menu.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Menus } from './menu.entity';
import { Repository } from 'typeorm';
import { UserService } from '../user/user.service';
import { MenusTree } from './dto/menu.dto';

@Injectable()
export class MenusService {
  constructor(
    @InjectRepository(Menus)
    private readonly menusRepository: Repository<Menus>,
    private readonly userService: UserService,
  ) { }

  findAllMenu() {
    return this.menusRepository.find();
  }

  async findAllMenuByUsername(username: string){
    const user = await this.userService.findByUsername(username);
    const roles = user.roles.map(role => role.id)

    const queryBuilder = this.menusRepository
      .createQueryBuilder('menus')
      .innerJoin('menus.role', 'role')
      .where("role.id IN (:...roleId)", { roleId: roles })
      .orderBy('menus.id', 'ASC')

    return queryBuilder.getMany();
    // const menusList = await queryBuilder.getMany();

    // return this.changeMenusArrayToTree(menusList)
  }

  // 递归函数，将数组转化为树形结构
  changeMenusArrayToTree(Menus: Menus[], parentId = 0){
    const result: MenusTree[] = []
    Menus.map(m => {
      if(m.parentId === parentId){
        const children = this.changeMenusArrayToTree(Menus, m.id)
        if(children.length > 0) result.push({...m, children, meta: JSON.parse(m.meta) })
        else result.push({...m, meta: JSON.parse(m.meta)})
      }
    })
    return result
  }

  async findActiveMenuByUsername(username: string){
    const user = await this.userService.findByUsername(username);
    const roles = user.roles.map(role => role.id)

    const queryBuilder = this.menusRepository
      .createQueryBuilder('menus')
      .innerJoin('menus.role', 'role')
      .where('menus.active = 1')
      .andWhere("role.id IN (:...roleId)", { roleId: roles })
      .orderBy('menus.parentId', 'ASC')
      .addOrderBy('menus.id', 'ASC')

    return queryBuilder.getMany();
  }

  async create(createMenuDto: CreateMenuDto) {
    const menu = await this.menusRepository.create(createMenuDto);
    return this.menusRepository.save(menu);
  }

  findOne(id: number) {
    return this.menusRepository.findOne({ where: { id } });
  }

  async update(updateMenuDto: UpdateMenuDto) {
    const { id } = updateMenuDto;
    const menu = await this.menusRepository.findOne({ where: { id } });
    const newMenu = this.menusRepository.merge(menu, updateMenuDto);
    return this.menusRepository.save(newMenu);
  }

  async remove(id: number) {
    const menu = await this.menusRepository.findOne({ where: { id } });
    return this.menusRepository.remove(menu);
  }
}
